package com.qgs.secsgem.secs.eq.runnable;

import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qgs.secsgem.mq.entity.CallbackMessageEntity;
import com.qgs.secsgem.mq.entity.MQMessage;
import com.qgs.secsgem.mq.entity.common.Header;
import com.qgs.secsgem.mq.producer.component.RabbitSender;
import com.qgs.secsgem.secs.SecsCommunicator;
import com.qgs.secsgem.secs.SecsException;
import com.qgs.secsgem.secs.SecsMessage;
import com.qgs.secsgem.secs.controller.SecsSerivce;
import com.qgs.secsgem.secs.entity.common.*;
import com.qgs.secsgem.secs.entity.eventBody.S2F33MesRequestBody;
import com.qgs.secsgem.secs.entity.eventBody.S2F35MesRequestBody;
import com.qgs.secsgem.secs.entity.eventBody.S2F37MesRequestBody;
import com.qgs.secsgem.secs.entity.eventBody.S6F23MesRequestBody;
import com.qgs.secsgem.secs.gem.*;
import com.qgs.secsgem.secs.hsms.HsmsConnectionMode;
import com.qgs.secsgem.secs.hsmsss.HsmsSsCommunicator;
import com.qgs.secsgem.secs.hsmsss.HsmsSsCommunicatorConfig;
import com.qgs.secsgem.secs.secs2.Secs2;
import com.qgs.secsgem.secs.secs2.Secs2Exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;


/**
 * @Desc: ""
 * @Author: caixiang
 * @DATE: 2023/4/12 11:01
 * 步骤：
 *      1.ctl+c 复制 PID10Runnable  ==>   PID4Runnable
 *      2.进入PID4Runnable 更改 进入PID4Runnable.VID_Type、PID4Runnable.ECID_Type
 *      3.(可选)在comm.addSecsCommunicatableStateChangeListener 里面配置 当新建立tcp连接后，是否是在 EAP-Server这里执行 S1F13+S1F17
 */
public class PID24aRunnable implements Runnable{

    private static final Logger logger = LoggerFactory.getLogger("PID24aLOGGER");

    private HsmsSsCommunicatorConfig config;

    public static HsmsSsCommunicator comm;

    private RabbitSender rabbitSender;

    private String exchangName;
    private String eapRequestRoutingKey;
    private String mesRequestRoutingKey;
    private String equipmentId;

    //默认值
    public static String SVID_Type = "U4";
    public static String ECID_Type = "U4";
    //eventid type
    public static String CEID_Type = "U4";
    public static String ALID_Type = "U4";
    //reportid type
    public static String REPORTID_Type = "U4";
    /**
     * 构造函数
     *
     * @param ip/port 线程名称
     */
    public PID24aRunnable(String equipmentId, String ip, Integer port, RabbitSender rabbitSender, String exchangName, String eapRequestRoutingKey, String mesRequestRoutingKey, String SVID_Type, String ECID_Type,String CEID_Type,String ALID_Type,String REPORTID_Type) {
        this.equipmentId = equipmentId;
        this.exchangName = exchangName;
        this.eapRequestRoutingKey = eapRequestRoutingKey;
        this.mesRequestRoutingKey = mesRequestRoutingKey;
        this.SVID_Type = SVID_Type;
        this.ECID_Type = ECID_Type;
        this.CEID_Type = CEID_Type;
        this.ALID_Type = ALID_Type;
        this.REPORTID_Type = REPORTID_Type;


        this.rabbitSender = rabbitSender;
        this.config = new HsmsSsCommunicatorConfig();
        this.config.socketAddress(new InetSocketAddress(ip, port));
        this.config.connectionMode(HsmsConnectionMode.ACTIVE);
        //默认sessionId=deviceId=0
        this.config.sessionId(0);
        this.config.isEquip(false);
        this.config.linktest(60.0F);
        this.config.timeout().t3(45.0F);
        this.config.timeout().t5(10.0F);
        this.config.timeout().t6( 5.0F);
        this.config.timeout().t8( 6.0F);
        //这里只是 new一个HsmsSsCommunicator 实例 ，还未open（还未启动）
        comm = HsmsSsCommunicator.newInstance(this.config);

    }

    //依据VID_TYPE 转换相应的VID


    public HsmsSsCommunicator getComm() {
        return comm;
    }

    public String getSVidType() {
        return SVID_Type;
    }

    private void sendMessageToMQ(CallbackMessageEntity callbackMessageEntity) throws Exception {
        MQMessage mqMessage = callbackMessageEntity.getMqMessage();
        String exchangeName =  callbackMessageEntity.getExchangeName();
        String routingKey =  callbackMessageEntity.getRoutingKey();


        rabbitSender.sendDirect(mqMessage,exchangeName,routingKey);
        logger.info("EAP => MES (EAP_Request), 状态：已收到 , 已入MQ , 内容："+ mqMessage.getHeader().toString());
    }

    //dc 从MQ 中接收 mes-request msg , 然后发送给EAP ，eap返回结果给dc ，dc 再把mes response 推送给mq 告知mes
    private void sendMessageToMQ(MQMessage mqMessage) throws Exception {
        rabbitSender.sendDirect(mqMessage,this.exchangName,this.mesRequestRoutingKey);
        logger.info("MES => EAP (MES_Response), 状态：DC已收到 , 已入MQ , 内容："+ mqMessage.toString());
    }





    private static ALCD parseALCD(String ss) {
        Character c1;
        Character c2;
        if(ss.length()!=2){
            c1 = '0';
            c2 = ss.charAt(0);
        }else {
            c1 = ss.charAt(0);
            c2 = ss.charAt(1);
        }



        Byte s = HexUtil.decodeHex(c1.toString())[0];
        String s1 = byteToBit(s);
        char[] s11 = s1.toCharArray();

        Byte d = HexUtil.decodeHex(c2.toString())[0];
        String d1 = byteToBit(d);
        char[] d11 = d1.toCharArray();

        int[] res = new int[8];
        res[0] = s11[4]=='1'? 1: 0;
        res[1] = s11[5]=='1'? 1: 0;
        res[2] = s11[6]=='1'? 1: 0;
        res[3] = s11[7]=='1'? 1: 0;

        res[4] = d11[4]=='1'? 1: 0;
        res[5] = d11[5]=='1'? 1: 0;
        res[6] = d11[6]=='1'? 1: 0;
        res[7] = d11[7]=='1'? 1: 0;
        String category = "";
        String alarmStatus = "0";
        if(res[0] == 1){
            alarmStatus = "1";
        }
        res[0] = (byte) 0;

        int i = convertByteArrayToInt(res);
        if(i==0){
            category = "Not used";
        }else if(i==1){
            category = "Personal safety";
        }else if(i == 2 ){
            category = "Equipment safety";
        }else if(i == 3 ){
            category = "Parameter control warning";
        }else if(i == 4 ){
            category = "Parameter control error";
        }else if(i == 5 ){
            category = "Irrecoverable error";
        }else if(i == 6 ){
            category = "Equipment status warning";
        }else if(i == 7 ){
            category = "Attention flags";
        }else if(i == 8 ){
            category = "Data integrity";
        }else {
            //如果i>8 那是保留的，就得问 设备商了。
            category = "Other categories";
        }

        ALCD alcd = new ALCD();
        alcd.setAlarmCategory(category);
        alcd.setAlarmState(alarmStatus);
        alcd.setAlcd(ss);
        return alcd;
    }

    public static int convertByteArrayToInt(int[] ints) {
        int res = 0;
        if(ints[0] == 1){
            res+=128;
        }
        if(ints[1] == 1){
            res+=64;
        }
        if(ints[2] == 1){
            res+=32;
        }
        if(ints[3] == 1){
            res+=16;
        }
        if(ints[4] == 1){
            res+=8;
        }
        if(ints[5] == 1){
            res+=4;
        }
        if(ints[6] == 1){
            res+=2;
        }
        if(ints[7] == 1){
            res+=1;
        }

        return res;
    }


    //S6F11 递归遍历 格式化 SECS结构为 标准格式 RecursiveFormatting
    public static List<ValueNode> get(JSONArray argList){
        //Set<ValueNode> set=new LinkedHashSet<>();
        List<ValueNode> set = new ArrayList<>();

        for(int i=0;i<argList.size();i++){
            if(argList.get(i) == null){
                continue;
            }
            JSONObject j = (JSONObject) argList.get(i);
            String type = j.getString("f");
            if(!type.equals("L")){
                set.add(new ValueNode(j.getString("f"),j.get("v").toString()));

            }else {
                //当嵌套里面还有嵌套，，这里顺序错了，修复一下。
                JSONArray array = j.getJSONArray("v");
                set.add(new ValueNode("List",get(array)));
            }
        }
        return set;
    }

    private void sendEapRequestToMQ(Header header, EventBody eventBody) throws Exception {
        //example for mq     -- 开始
        //往MQ 里面发一条 测试数据
        CallbackMessageEntity callbackMessageEntity2 = new CallbackMessageEntity();
        MQMessage mqMessage = new MQMessage();

        mqMessage.setBody(JSONObject.toJSONString(eventBody));
        mqMessage.setHeader(header);
        callbackMessageEntity2.setMqMessage(mqMessage);
        callbackMessageEntity2.setExchangeName(exchangName);
        callbackMessageEntity2.setRoutingKey(eapRequestRoutingKey);
        sendMessageToMQ(callbackMessageEntity2);
        //example for mq     -- 结束

    }

    private void sendEapRequestToMQ(Header header, AlarmBody alarmBody) throws Exception {
        //example for mq     -- 开始
        //往MQ 里面发一条 测试数据
        CallbackMessageEntity callbackMessageEntity2 = new CallbackMessageEntity();
        MQMessage mqMessage = new MQMessage();

        mqMessage.setBody(JSONObject.toJSONString(alarmBody));
        mqMessage.setHeader(header);
        callbackMessageEntity2.setMqMessage(mqMessage);
        callbackMessageEntity2.setExchangeName(exchangName);
        callbackMessageEntity2.setRoutingKey(eapRequestRoutingKey);
        sendMessageToMQ(callbackMessageEntity2);
        //example for mq     -- 结束

    }

    private void sendEapRequestToMQ(Header header, TraceDataBody traceDataBody) throws Exception {
        //example for mq     -- 开始
        //往MQ 里面发一条 测试数据
        CallbackMessageEntity callbackMessageEntity2 = new CallbackMessageEntity();
        MQMessage mqMessage = new MQMessage();

        mqMessage.setBody(JSONObject.toJSONString(traceDataBody));
        mqMessage.setHeader(header);
        callbackMessageEntity2.setMqMessage(mqMessage);
        callbackMessageEntity2.setExchangeName(exchangName);
        callbackMessageEntity2.setRoutingKey(eapRequestRoutingKey);
        sendMessageToMQ(callbackMessageEntity2);
        //example for mq     -- 结束
    }

    private void sendEapRequestToMQ(Header header) throws Exception {
        //example for mq     -- 开始
        //往MQ 里面发一条 测试数据
        CallbackMessageEntity callbackMessageEntity2 = new CallbackMessageEntity();
        MQMessage mqMessage = new MQMessage();
        mqMessage.setHeader(header);
        callbackMessageEntity2.setMqMessage(mqMessage);
        callbackMessageEntity2.setExchangeName(exchangName);
        callbackMessageEntity2.setRoutingKey(eapRequestRoutingKey);
        sendMessageToMQ(callbackMessageEntity2);
        //example for mq     -- 结束
    }

    /**
     * 把byte转为字符串的bit
     */
    public static String byteToBit(byte b) {
        return ""
                + (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1)
                + (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1)
                + (byte) ((b >> 3) & 0x1) + (byte) ((b >> 2) & 0x1)
                + (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1);
    }


    /**
     * 重写run方法
     */
    @Override
    public void run() {
        try {

            //这个lambda函数 ，是 SecsLogListener 接口的 received函数的实现，
            // 并且通过addSecsLogListener，把这个实现注册到全局的AbstractSecsCommunicator 这个顶层抽象类中的一个成员变量中去
            comm.addSecsLogListener(msg ->{
                //log out message
//                System.out.println("\n{\nPID24a EAP Server : \n"+msg.toString()+"\n}\n");
                logger.info("\n{\nPID24a EAP Server : \n"+msg.toString()+"\n}\n");
            });

            //当收到SxFy时候的回调
            comm.addSecsMessageReceiveListener(msg -> {
                String json = msg.toJson();

                /* Nothing */
                try {
                    if(msg.wbit()){
                        if (msg.getStream() ==1 && msg.getFunction() ==1){
                            //写业务
                            Header header = new Header("Request","Execute","GeneratePingRequest",equipmentId);
                            sendEapRequestToMQ(header);
                        }
                        else if (msg.getStream() ==1 && msg.getFunction() ==13){
                            //写业务
                        }else if (msg.getStream() ==6 && msg.getFunction() ==1){
                            //
                            //TODO JSON => 标准JSON
                            JSONObject secsObject = JSONObject.parseObject(json);
                            JSONObject secs2 = secsObject.getJSONObject("secs2");
                            JSONArray v = secs2.getJSONArray("v");
                            String trid = "";
                            String tridType = v.getJSONObject(0).getString("f"); //20,3x,5x
                            if(tridType.equals("A")){
                                trid = v.getJSONObject(0).getString("v");
                            }else {
                                trid = v.getJSONObject(0).getJSONArray("v").getInteger(0).toString();
                            }
                            Integer smpln = v.getJSONObject(1).getJSONArray("v").getInteger(0);
                            String stime = v.getJSONObject(2).getString("v");

                            List<ValueNode> svs = new ArrayList<>();

                            Header header = new Header("Request","Event","TraceData",equipmentId);


                            if(v.getJSONObject(3)!=null){
                                //content 才是真正的
                                JSONArray content =  v.getJSONObject(3).getJSONArray("v");
                                svs = get(content);
                            }
                            TraceDataBody traceDataBody = new TraceDataBody(trid,tridType,smpln,stime,svs);
                            //发送消息到MQ
                            sendEapRequestToMQ(header, traceDataBody);

                        }
                        else if (msg.getStream() ==5 && msg.getFunction() ==1){
                            //alarm report
                            JSONObject secsObject = JSONObject.parseObject(json);
                            JSONObject secs2 = secsObject.getJSONObject("secs2");
                            JSONArray v = secs2.getJSONArray("v");
                            Byte alcd = v.getJSONObject(0).getJSONArray("v").getByte(0);
                            ALCD alcd1 = parseALCD(alcd.toString());

                            Integer alid = v.getJSONObject(1).getJSONArray("v").getInteger(0);

                            String altx_v =v.getJSONObject(2).getString("v");


                            AlarmBody body = new AlarmBody(alcd1,alid,altx_v);
                            Header header = new Header("Request","Alarm","AlarmReport",equipmentId);
                            sendEapRequestToMQ(header,body);

                        }
                        else if (msg.getStream() ==6 && msg.getFunction() ==11){

                            //TODO JSON => 标准JSON
                            JSONObject secsObject = JSONObject.parseObject(json);
                            JSONObject secs2 = secsObject.getJSONObject("secs2");
                            JSONArray v = secs2.getJSONArray("v");
                            Integer ceid = v.getJSONObject(1).getJSONArray("v").getInteger(0);
                            List<ReportNode> rptList = new ArrayList<>();
                            EventBody eventBody = new EventBody(ceid.toString(),rptList);
                            Header header = new Header("Request","Event","EventReport",equipmentId);


                            if(v.getJSONObject(2)!=null){
                                //content 才是真正的
                                JSONArray content =  v.getJSONObject(2).getJSONArray("v");

                                for(int i=0;i<content.size();i++){
                                    ReportNode report = null;
                                    JSONObject reportObj = content.getJSONObject(i);
                                    if(reportObj!=null){
                                        JSONArray array = reportObj.getJSONArray("v");
                                        String rptIdType = array.getJSONObject(0).getString("f");
                                        String rptId = array.getJSONObject(0).getJSONArray("v").getInteger(0).toString();
                                        JSONArray relContent = array.getJSONObject(1).getJSONArray("v");
                                        List<ValueNode> valueNodes = get(relContent);
                                        report = new ReportNode(rptId,rptIdType,valueNodes);
                                        rptList.add(report);
                                    }
                                }
                                System.out.println();
                            }

                            //发送消息到MQ
                            sendEapRequestToMQ(header, eventBody);

                        }
                    }else {
                    }

                    //统一回复
                    response(comm, msg);
                }catch (Exception e){
                    e.printStackTrace();
                    logger.info(e.getMessage());
                }
            });

            comm.addLinktestReceiveListener(lst->{
                logger.info("linktest lst:"+lst.toString());
            });

            //这里的通讯状态 state 只有true、false, true= SELECTED状态
            comm.addSecsCommunicatableStateChangeListener(state -> {

                //这里主要是做一些初始化的动作。S1F13+S1F17+...
                try {

                    if ( state /* SELECTED */ ) {
                        logger.info("CommunicatableStateChange state: SELECTED");

                        {
                            //向设备发起S1F13事件，请求建立通联连接
                            COMMACK commack = SecsSerivce.doS1F13(comm);
                            if(commack.equals(COMMACK.OK)){
                                logger.info("Initial S1F13 OK!");
                            }else {
                                logger.info("Initial S1F13 FAIL!");
                            }
                        }

                        {
                            //向设备发起S1F17事件，请求建立通联连接
                            ONLACK onlack = SecsSerivce.doS1F17(comm);
                            if(onlack.equals(ONLACK.OK)){
                                logger.info("Initial S1F17 OK!");
                            }else {
                                logger.info("Initial S1F17 FAIL!");
                            }
                        }

                        {
                            //spooling 相关
                            //1.向设备发起S2F37事件，enable all event
//                            ①.enable 指定ceid
//                            List<String> ceids = new ArrayList<>();
//                            ceids.add("101");
//                            ceids.add("102");
//                            ceids.add("103");

                            //②.enable all ceid
                            List<String> ceids = new ArrayList<>();
                            S2F37MesRequestBody s2F37MesRequestBody = new S2F37MesRequestBody(ceids,"U4",true);
                            if(SecsSerivce.doS2F37(comm, s2F37MesRequestBody)){
                                logger.info("Initial SPOOLING S2F37 OK!");
                            }else {
                                logger.info("Initial SPOOLING S2F37 FAIL!");
                            }

                            //2.S6F23 request spooling data
                            S6F23MesRequestBody s6F23MesRequestBody = new S6F23MesRequestBody(0);
                            if(SecsSerivce.doS6F23(comm,s6F23MesRequestBody)){
                                logger.info("Initial SPOOLING S6F23 OK!");
                            }else {
                                logger.info("Initial SPOOLING S6F23 FAIL!");
                            }

                        }

                        {
                            //Deletes All Report, Link Definition and Disable Alarm
                            List<String> ceids = new ArrayList<>();
                            S2F37MesRequestBody s2F37MesRequestBody = new S2F37MesRequestBody(ceids,"U4",false);
                            if(SecsSerivce.doS2F37(comm, s2F37MesRequestBody)){
                                logger.info("Initial Report(Delete) S2F37 OK!");
                            }else {
                                logger.info("Initial Report(Delete) S2F37 FAIL!");
                            }

                            S2F35MesRequestBody s2F35MesRequestBody = new S2F35MesRequestBody(new ArrayList<>());
                            if(SecsSerivce.doS2F35(comm, s2F35MesRequestBody)){
                                logger.info("Initial Report(Delete) S2F35 OK!");
                            }else {
                                logger.info("Initial Report(Delete) S2F35 FAIL!");
                            }

                            S2F33MesRequestBody s2F33MesRequestBody = new S2F33MesRequestBody(new ArrayList<>());
                            if(SecsSerivce.doS2F33(comm, s2F33MesRequestBody)){
                                logger.info("Initial Report(Delete) S2F33 OK!");
                            }else {
                                logger.info("Initial Report(Delete) S2F33 FAIL!");
                            }
                        }

                        {
                            {
                                //1.define report
                                //构建body   开始
                                List<ReportNode> reportNodes = new ArrayList<>();
                                //report1
                                //注意：vids要按顺序
                                //1. 这个代表给 reportId=1001 定义以下 vids
                                List<ValueNode> vids1 = new ArrayList<>();
                                vids1.add(new ValueNode("U4",3));
                                vids1.add(new ValueNode("U4",500));
                                vids1.add(new ValueNode("U4",11));
                                vids1.add(new ValueNode("U4",13));
                                vids1.add(new ValueNode("U4",14));
                                //2. 这样代表 删除 reportId=1001  下的所有vids（因为vids 是空）
                                reportNodes.add(createReport("1",PID24aRunnable.REPORTID_Type,vids1));
                                //report2
                                List<ValueNode> vids2 = new ArrayList<>();
                                vids2.add(new ValueNode("U4",3));
                                vids2.add(new ValueNode("U4",500));
                                vids2.add(new ValueNode("U4",11));
                                vids2.add(new ValueNode("U4",13));
                                vids2.add(new ValueNode("U4",14));
                                reportNodes.add(createReport("2",PID24aRunnable.REPORTID_Type,vids2));

                                List<ValueNode> vids3 = new ArrayList<>();
                                vids3.add(new ValueNode("U4",3));
                                vids3.add(new ValueNode("U4",500));
                                vids3.add(new ValueNode("U4",11));
                                vids3.add(new ValueNode("U4",13));
                                vids3.add(new ValueNode("U4",14));
                                reportNodes.add(createReport("3",PID24aRunnable.REPORTID_Type,vids3));

                                List<ValueNode> vids11 = new ArrayList<>();
                                vids11.add(new ValueNode("U4",3));
                                vids11.add(new ValueNode("U4",5));
                                vids11.add(new ValueNode("U4",6));
                                vids11.add(new ValueNode("U4",7));
                                reportNodes.add(createReport("11",PID24aRunnable.REPORTID_Type,vids11));

                                List<ValueNode> vids12 = new ArrayList<>();
                                vids12.add(new ValueNode("U4",3));
                                vids12.add(new ValueNode("U4",5));
                                vids12.add(new ValueNode("U4",6));
                                vids12.add(new ValueNode("U4",7));
                                reportNodes.add(createReport("12",PID24aRunnable.REPORTID_Type,vids12));

                                List<ValueNode> vids21 = new ArrayList<>();
                                vids21.add(new ValueNode("U4",3));
                                vids21.add(new ValueNode("U4",41));
                                vids21.add(new ValueNode("U4",45));
                                vids21.add(new ValueNode("U4",46));
                                vids21.add(new ValueNode("U4",47));
                                vids21.add(new ValueNode("U4",48));
                                reportNodes.add(createReport("21",PID24aRunnable.REPORTID_Type,vids21));

                                List<ValueNode> vids22 = new ArrayList<>();
                                vids22.add(new ValueNode("U4",3));
                                vids22.add(new ValueNode("U4",41));
                                vids22.add(new ValueNode("U4",45));
                                vids22.add(new ValueNode("U4",46));
                                vids22.add(new ValueNode("U4",47));
                                vids22.add(new ValueNode("U4",48));
                                reportNodes.add(createReport("22",PID24aRunnable.REPORTID_Type,vids22));

                                List<ValueNode> vids23 = new ArrayList<>();
                                vids23.add(new ValueNode("U4",3));
                                vids23.add(new ValueNode("U4",41));
                                vids23.add(new ValueNode("U4",45));
                                vids23.add(new ValueNode("U4",46));
                                vids23.add(new ValueNode("U4",47));
                                vids23.add(new ValueNode("U4",48));
                                reportNodes.add(createReport("23",PID24aRunnable.REPORTID_Type,vids23));

                                List<ValueNode> vids40 = new ArrayList<>();
                                vids40.add(new ValueNode("U4",3));
                                vids40.add(new ValueNode("U4",72));
                                vids40.add(new ValueNode("U4",1000));
                                vids40.add(new ValueNode("U4",1101));
                                vids40.add(new ValueNode("U4",1100));
                                reportNodes.add(createReport("40",PID24aRunnable.REPORTID_Type,vids40));

                                List<ValueNode> vids41 = new ArrayList<>();
                                vids41.add(new ValueNode("U4",3));
                                vids41.add(new ValueNode("U4",1000));
                                vids41.add(new ValueNode("U4",1101));
                                vids41.add(new ValueNode("U4",1100));
                                reportNodes.add(createReport("41",PID24aRunnable.REPORTID_Type,vids41));

                                List<ValueNode> vids42 = new ArrayList<>();
                                vids42.add(new ValueNode("U4",3));
                                vids42.add(new ValueNode("U4",72));
                                vids42.add(new ValueNode("U4",1002));
                                vids42.add(new ValueNode("U4",1102));
                                reportNodes.add(createReport("42",PID24aRunnable.REPORTID_Type,vids42));

                                List<ValueNode> vids43 = new ArrayList<>();
                                vids43.add(new ValueNode("U4",3));
                                vids43.add(new ValueNode("U4",72));
                                vids43.add(new ValueNode("U4",1003));
                                vids43.add(new ValueNode("U4",1103));
                                vids43.add(new ValueNode("U4",1101));
                                vids43.add(new ValueNode("U4",1108));
                                vids43.add(new ValueNode("U4",2000));
                                vids43.add(new ValueNode("U4",2001));
                                vids43.add(new ValueNode("U4",2002));
                                vids43.add(new ValueNode("U4",2003));
                                vids43.add(new ValueNode("U4",2004));
                                vids43.add(new ValueNode("U4",2005));
                                vids43.add(new ValueNode("U4",2006));
                                vids43.add(new ValueNode("U4",2007));
                                vids43.add(new ValueNode("U4",2008));
                                vids43.add(new ValueNode("U4",2009));
                                vids43.add(new ValueNode("U4",2010));
                                vids43.add(new ValueNode("U4",2011));
                                vids43.add(new ValueNode("U4",2012));
                                vids43.add(new ValueNode("U4",2013));
                                vids43.add(new ValueNode("U4",2014));
                                vids43.add(new ValueNode("U4",2015));
                                vids43.add(new ValueNode("U4",2016));
                                vids43.add(new ValueNode("U4",2017));
                                vids43.add(new ValueNode("U4",2018));
                                vids43.add(new ValueNode("U4",2019));
                                vids43.add(new ValueNode("U4",2020));
                                vids43.add(new ValueNode("U4",2021));
                                vids43.add(new ValueNode("U4",2022));
                                vids43.add(new ValueNode("U4",2023));
                                vids43.add(new ValueNode("U4",2024));
                                vids43.add(new ValueNode("U4",2025));
                                vids43.add(new ValueNode("U4",2026));
                                vids43.add(new ValueNode("U4",2027));
                                vids43.add(new ValueNode("U4",2028));
                                vids43.add(new ValueNode("U4",2029));
                                vids43.add(new ValueNode("U4",2030));
                                vids43.add(new ValueNode("U4",2031));
                                vids43.add(new ValueNode("U4",2032));
                                vids43.add(new ValueNode("U4",2033));
                                vids43.add(new ValueNode("U4",2034));
                                vids43.add(new ValueNode("U4",2035));
                                vids43.add(new ValueNode("U4",2036));
                                vids43.add(new ValueNode("U4",2037));
                                vids43.add(new ValueNode("U4",2038));
                                vids43.add(new ValueNode("U4",2039));
                                vids43.add(new ValueNode("U4",2040));
                                vids43.add(new ValueNode("U4",2041));
                                vids43.add(new ValueNode("U4",2042));
                                vids43.add(new ValueNode("U4",2043));
                                vids43.add(new ValueNode("U4",2044));
                                vids43.add(new ValueNode("U4",2045));
                                vids43.add(new ValueNode("U4",2046));
                                reportNodes.add(createReport("43",PID24aRunnable.REPORTID_Type,vids43));

                                List<ValueNode> vids44 = new ArrayList<>();
                                vids44.add(new ValueNode("U4",3));
                                vids44.add(new ValueNode("U4",72));
                                vids44.add(new ValueNode("U4",1007));
                                vids44.add(new ValueNode("U4",1107));
                                vids44.add(new ValueNode("U4",1101));
                                vids44.add(new ValueNode("U4",1108));
                                reportNodes.add(createReport("44",PID24aRunnable.REPORTID_Type,vids44));

                                List<ValueNode> vids70 = new ArrayList<>();
                                vids70.add(new ValueNode("U4",3));
                                vids70.add(new ValueNode("U4",51));
                                reportNodes.add(createReport("70",PID24aRunnable.REPORTID_Type,vids70));

                                List<ValueNode> vids80 = new ArrayList<>();
                                vids80.add(new ValueNode("U4",3));
                                vids80.add(new ValueNode("U4",60));
                                vids80.add(new ValueNode("U4",61));
                                reportNodes.add(createReport("80",PID24aRunnable.REPORTID_Type,vids80));

                                List<ValueNode> vids90 = new ArrayList<>();
                                vids90.add(new ValueNode("U4",3));
                                vids90.add(new ValueNode("U4",70));
                                vids90.add(new ValueNode("U4",71));
                                reportNodes.add(createReport("90",PID24aRunnable.REPORTID_Type,vids90));

                                List<ValueNode> vids91 = new ArrayList<>();
                                vids91.add(new ValueNode("U4",3));
                                vids91.add(new ValueNode("U4",70));
                                vids91.add(new ValueNode("U4",71));
                                reportNodes.add(createReport("91",PID24aRunnable.REPORTID_Type,vids91));

                                List<ValueNode> vids92 = new ArrayList<>();
                                vids92.add(new ValueNode("U4",3));
                                vids92.add(new ValueNode("U4",70));
                                vids92.add(new ValueNode("U4",71));
                                reportNodes.add(createReport("92",PID24aRunnable.REPORTID_Type,vids92));

                                List<ValueNode> vids93 = new ArrayList<>();
                                vids93.add(new ValueNode("U4",3));
                                vids93.add(new ValueNode("U4",70));
                                vids93.add(new ValueNode("U4",71));
                                reportNodes.add(createReport("93",PID24aRunnable.REPORTID_Type,vids93));

                                List<ValueNode> vids110 = new ArrayList<>();
                                vids110.add(new ValueNode("U4",3));
                                vids110.add(new ValueNode("U4",500));
                                vids110.add(new ValueNode("U4",501));
                                reportNodes.add(createReport("110",PID24aRunnable.REPORTID_Type,vids110));

                                List<ValueNode> vids111 = new ArrayList<>();
                                vids111.add(new ValueNode("U4",3));
                                vids111.add(new ValueNode("U4",500));
                                vids111.add(new ValueNode("U4",501));
                                reportNodes.add(createReport("111",PID24aRunnable.REPORTID_Type,vids111));

                                List<ValueNode> vids120 = new ArrayList<>();
                                vids120.add(new ValueNode("U4",3));
                                vids120.add(new ValueNode("U4",201));
                                vids120.add(new ValueNode("U4",200));
                                reportNodes.add(createReport("120",PID24aRunnable.REPORTID_Type,vids120));

                                List<ValueNode> vids121 = new ArrayList<>();
                                vids121.add(new ValueNode("U4",3));
                                vids121.add(new ValueNode("U4",201));
                                vids121.add(new ValueNode("U4",200));
                                reportNodes.add(createReport("121",PID24aRunnable.REPORTID_Type,vids121));

                                List<ValueNode> vids130 = new ArrayList<>();
                                vids130.add(new ValueNode("U4",3));
                                vids130.add(new ValueNode("U4",4200));
                                vids130.add(new ValueNode("U4",4201));
                                reportNodes.add(createReport("130",PID24aRunnable.REPORTID_Type,vids130));

                                S2F33MesRequestBody s2F33MesRequestBody = new S2F33MesRequestBody(reportNodes);
                                //构建body   结束
                                if(SecsSerivce.doS2F33(comm, s2F33MesRequestBody)){
                                    logger.info("Initial Report(Define) S2F33 OK!");
                                }else {
                                    logger.info("Initial Report(Define) S2F33 FAIL!");
                                }
                            }
                            {
                                //构建body   开始
                                List<ReportEventNode> reportEventNodes = new ArrayList<>();

                                //report-event link 1
                                //注意：reportIds要按顺序
                                //1. 这个代表给 ceid=101 定义以下 reportIds
                                List<ValueNode> rptids1 = new ArrayList<>();
                                rptids1.add(new ValueNode("U4",1));
                                //2. 这样代表 删除 reportId=1001  下的所有vids（因为vids 是空）
                                reportEventNodes.add(createReportEvent("1",PID24aRunnable.CEID_Type,rptids1));

                                //report-event link 2
                                List<ValueNode> rptids2 = new ArrayList<>();
                                rptids2.add(new ValueNode("U4",2));
                                reportEventNodes.add(createReportEvent("2",PID24aRunnable.CEID_Type,rptids2));

                                List<ValueNode> rptids3 = new ArrayList<>();
                                rptids3.add(new ValueNode("U4",3));
                                reportEventNodes.add(createReportEvent("3",PID24aRunnable.CEID_Type,rptids3));

                                List<ValueNode> rptids11 = new ArrayList<>();
                                rptids11.add(new ValueNode("U4",11));
                                reportEventNodes.add(createReportEvent("11",PID24aRunnable.CEID_Type,rptids11));

                                List<ValueNode> rptids12 = new ArrayList<>();
                                rptids12.add(new ValueNode("U4",12));
                                reportEventNodes.add(createReportEvent("12",PID24aRunnable.CEID_Type,rptids12));

                                List<ValueNode> rptids21 = new ArrayList<>();
                                rptids21.add(new ValueNode("U4",21));
                                reportEventNodes.add(createReportEvent("21",PID24aRunnable.CEID_Type,rptids21));

                                List<ValueNode> rptids22 = new ArrayList<>();
                                rptids22.add(new ValueNode("U4",22));
                                reportEventNodes.add(createReportEvent("22",PID24aRunnable.CEID_Type,rptids22));

                                List<ValueNode> rptids23 = new ArrayList<>();
                                rptids23.add(new ValueNode("U4",23));
                                reportEventNodes.add(createReportEvent("23",PID24aRunnable.CEID_Type,rptids23));

                                List<ValueNode> rptids40 = new ArrayList<>();
                                rptids40.add(new ValueNode("U4",40));
                                reportEventNodes.add(createReportEvent("40",PID24aRunnable.CEID_Type,rptids40));

                                List<ValueNode> rptids41 = new ArrayList<>();
                                rptids41.add(new ValueNode("U4",41));
                                reportEventNodes.add(createReportEvent("41",PID24aRunnable.CEID_Type,rptids41));

                                List<ValueNode> rptids42 = new ArrayList<>();
                                rptids42.add(new ValueNode("U4",42));
                                reportEventNodes.add(createReportEvent("42",PID24aRunnable.CEID_Type,rptids42));

                                List<ValueNode> rptids43 = new ArrayList<>();
                                rptids43.add(new ValueNode("U4",43));
                                reportEventNodes.add(createReportEvent("43",PID24aRunnable.CEID_Type,rptids43));

                                List<ValueNode> rptids44 = new ArrayList<>();
                                rptids44.add(new ValueNode("U4",44));
                                reportEventNodes.add(createReportEvent("44",PID24aRunnable.CEID_Type,rptids44));

                                List<ValueNode> rptids70 = new ArrayList<>();
                                rptids70.add(new ValueNode("U4",70));
                                reportEventNodes.add(createReportEvent("70",PID24aRunnable.CEID_Type,rptids70));

                                List<ValueNode> rptids80 = new ArrayList<>();
                                rptids80.add(new ValueNode("U4",80));
                                reportEventNodes.add(createReportEvent("80",PID24aRunnable.CEID_Type,rptids80));

                                List<ValueNode> rptids90 = new ArrayList<>();
                                rptids90.add(new ValueNode("U4",90));
                                reportEventNodes.add(createReportEvent("90",PID24aRunnable.CEID_Type,rptids90));

                                List<ValueNode> rptids91 = new ArrayList<>();
                                rptids91.add(new ValueNode("U4",91));
                                reportEventNodes.add(createReportEvent("91",PID24aRunnable.CEID_Type,rptids91));

                                List<ValueNode> rptids92 = new ArrayList<>();
                                rptids92.add(new ValueNode("U4",92));
                                reportEventNodes.add(createReportEvent("92",PID24aRunnable.CEID_Type,rptids92));

                                List<ValueNode> rptids93 = new ArrayList<>();
                                rptids93.add(new ValueNode("U4",93));
                                reportEventNodes.add(createReportEvent("93",PID24aRunnable.CEID_Type,rptids93));

                                List<ValueNode> rptids110 = new ArrayList<>();
                                rptids110.add(new ValueNode("U4",110));
                                reportEventNodes.add(createReportEvent("110",PID24aRunnable.CEID_Type,rptids110));

                                List<ValueNode> rptids111 = new ArrayList<>();
                                rptids111.add(new ValueNode("U4",111));
                                reportEventNodes.add(createReportEvent("111",PID24aRunnable.CEID_Type,rptids111));

                                List<ValueNode> rptids120 = new ArrayList<>();
                                rptids120.add(new ValueNode("U4",120));
                                reportEventNodes.add(createReportEvent("120",PID24aRunnable.CEID_Type,rptids120));

                                List<ValueNode> rptids121 = new ArrayList<>();
                                rptids121.add(new ValueNode("U4",121));
                                reportEventNodes.add(createReportEvent("121",PID24aRunnable.CEID_Type,rptids121));

                                List<ValueNode> rptids130 = new ArrayList<>();
                                rptids130.add(new ValueNode("U4",130));
                                reportEventNodes.add(createReportEvent("130",PID24aRunnable.CEID_Type,rptids130));


                                S2F35MesRequestBody s2F35MesRequestBody = new S2F35MesRequestBody(reportEventNodes);


                                //构建body   结束

                                if(SecsSerivce.doS2F35(comm, s2F35MesRequestBody)){
                                    logger.info("Initial Report(Define) S2F35 OK!");
                                }else {
                                    logger.info("Initial Report(Define) S2F35 FAIL!");
                                }
                            }
                            {
                                List<String> ceids = new ArrayList<>();
                                S2F37MesRequestBody s2F37MesRequestBody = new S2F37MesRequestBody(ceids,"U4",true);
                                if(SecsSerivce.doS2F37(comm, s2F37MesRequestBody)){
                                    logger.info("Initial Report(Define) S2F37 OK!");
                                }else {
                                    logger.info("Initial Report(Define) S2F37 FAIL!");
                                }
                            }
                        }




                    }else {
                        logger.info("CommunicatableStateChange state: NOT SELECTED OR NOT CONNECTED");
                    }

                } catch (InterruptedException | SecsException ignore ) {
                    ignore.printStackTrace();
                    logger.info("出现中断异常 ："+ignore.getMessage());
                } catch (Secs2Exception e) {
                    throw new RuntimeException(e);
                }


            });

            comm.open();


            synchronized ( PID24aRunnable.class ) {
                PID24aRunnable.class.wait();
            }
        } catch ( Throwable e ) {
            //把它置为空，到时候就会自动被GC回收
            comm = null;
            e.printStackTrace();
        }


    }
    private ReportNode createReport(String reportId,String reportIdType,List<ValueNode> valueNodes) {
        ReportNode reportNode = new ReportNode();
        reportNode.setReportId(reportId);
        reportNode.setReportIdType(reportIdType);
        reportNode.setValueList(valueNodes);
        return reportNode;
    }
    private ReportEventNode createReportEvent(String ceid,String ceidType,List<ValueNode> valueNodes) {
        ReportEventNode reportEventNode = new ReportEventNode();
        reportEventNode.setCeid(ceid);
        reportEventNode.setCeidType(ceidType);
        reportEventNode.setValueNodes(valueNodes);
        return reportEventNode;
    }
    private static void response(SecsCommunicator comm, SecsMessage msg)
            throws InterruptedException, SecsException {

        int strm = msg.getStream();
        int func = msg.getFunction();
        boolean wbit = msg.wbit();
        Secs2 secs2 = msg.secs2();
        try {
             if(wbit){
                 switch ( strm ) {
                     case 1: {

                         switch ( func ) {
                             case 1: {

                                 if ( wbit ) {
                                     comm.gem().s1f2(msg);
                                 }
                                 break;
                             }
                             case 13: {

                                 if ( wbit ) {
                                     comm.gem().s1f14(msg, COMMACK.OK);
//								comm.gem().s1f1();
                                 }
                                 break;
                             }
                             case 15: {

                                 if ( wbit ) {
                                     comm.gem().s1f16(msg);
                                 }
                                 break;
                             }
                             case 17: {

                                 if ( wbit ) {
                                     comm.gem().s1f18(msg, ONLACK.OK);
                                 }
                                 break;
                             }
                             default: {

                                 if ( wbit ) {
                                     comm.send(msg, strm, 0, false);
                                 }

                                 comm.gem().s9f5(msg);
                             }
                         }

                         break;
                     }

                     case 2: {

                         switch ( func ) {

                             case 21: {

                                 String rcmd = secs2.getAscii();
                                 System.out.println(rcmd);

                                 if ( wbit ) {
                                     comm.gem().s2f22(msg, CMDA.CommandDoesNotExist);
                                 }
                                 break;
                             }
                             case 31: {

                                 String time = secs2.getAscii();
                                 System.out.println(time);

                                 if ( wbit ) {
                                     comm.gem().s2f32(msg, TIACK.OK);
                                 }
                                 break;
                             }
                             default: {

                                 if ( wbit ) {
                                     comm.send(msg, strm, 0, false);
                                 }

                                 comm.gem().s9f5(msg);
                             }
                         }

                         break;
                     }
                     case 5: {

                         switch ( func ) {

                             case 1: {

                                 if ( wbit ) {
                                     comm.gem().s5f2(msg, ACKC5.OK);
                                 }
                                 break;
                             }
                             default: {

                                 if ( wbit ) {
                                     comm.send(msg, strm, 0, false);
                                 }

                                 comm.gem().s9f5(msg);

                             }
                         }

                         break;
                     }
                     case 6: {

                         switch ( func ) {
                             case 1: {

                                 if ( wbit ) {
                                     comm.gem().s6f2(msg, ACKC6.OK);
                                 }
                                 break;
                             }
                             case 11: {

                                 if ( wbit ) {
                                     comm.gem().s6f12(msg, ACKC6.OK);
                                 }
                                 break;
                             }
                             default: {

                                 if ( wbit ) {
                                     comm.send(msg, strm, 0, false);
                                 }

                                 comm.gem().s9f5(msg);
                             }
                         }

                         break;
                     }
                     case 10: {

                         switch ( func ) {
                             case 3: {

                                 /*
                                  * Terminal Display, Single-Block
                                  * format
                                  * S10F3 W
                                  * <L
                                  *   <B[1] TID>
                                  *   <A[n] display-text>
                                  * >
                                  */

                                 String dispText = secs2.getAscii(1);

                                 System.out.println(dispText);

                                 if ( wbit ) {
                                     comm.gem().s10f4(msg, ACKC10.AcceptedForDisplay);
                                 }
                                 break;
                             }
                             case 5: {

                                 /*
                                  * Terminal Display, Multi-Block
                                  * format:
                                  * S10F5 W
                                  * <L
                                  *   <B[1] TID>
                                  *   <L[n]
                                  *     <A block-1>
                                  *     <A block-2>
                                  *     ...
                                  *   >
                                  * >
                                  */

                                 Secs2 ss = secs2.get(1);

                                 /* AbstractSecs2 implements Iterable */
                                 for ( Secs2 s : ss ) {
                                     String dispText = s.getAscii();
                                     System.out.println(dispText);
                                 }

                                 if ( wbit ) {
                                     comm.gem().s10f6(msg, ACKC10.AcceptedForDisplay);
                                 }

                                 break;
                             }
                             default: {

                                 if ( wbit ) {
                                     comm.send(msg, strm, 0, false);
                                 }

                                 comm.gem().s9f5(msg);
                             }
                         }

                         break;
                     }

                     default: {

                         if ( wbit ) {
                             comm.send(msg, strm, 0, false);
                         }

                         comm.gem().s9f3(msg);
                     }
                 }
             }

        } catch ( Secs2Exception e ) {

            comm.gem().s9f7(msg);
        }
    }
}
